package tw.rescue.dao.impl.slim3;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.ModelQuery;
import org.slim3.datastore.S3QueryResultList;
import com.google.appengine.api.datastore.Key;
import tw.rescue.dao.GuestBookDao;
import tw.rescue.slim3.meta.GuestBookMessageMeta;
import tw.rescue.slim3.model.GuestBookMessage;

public class Slim3GuestBookDaoImpl extends Slim3BaseDaoImpl implements GuestBookDao<Key, QueryStateHolder<GuestBookMessage>> {

	public void deleteMessage(Key key) {
		Datastore.delete(key);
	}

	public void topMessage(Key key, boolean isTop) {
		// TODO
	}

	public void markMessage(Key key, boolean isMarked) {
		// TODO
	}

	public void newMessage(GuestBookMessage message) {
		Key key = Datastore.allocateId(GuestBookMessage.class);
		message.setKey(key);
		message.setRoot(true);
		if (message.getCreateTime()==null)
			message.setCreateTime(new Date());
		Datastore.put(message);
	}

	public QueryStateHolder<GuestBookMessage> queryMessages(String category, int count) {
		if (count<=0 || count>1000)
			throw new NullPointerException("queryMessageKeys: count should be between 1 and 1000!");
		GuestBookMessageMeta meta = GuestBookMessageMeta.get();
		ModelQuery<GuestBookMessage>q = Datastore.query(meta);
		if (!StringUtils.isBlank(category))
			q.filter(meta.categories.equal(category));
		S3QueryResultList<GuestBookMessage>s3qlist = q.sort(meta.createTime.desc)
			.limit(count).asQueryResultList();
		QueryStateHolder<GuestBookMessage> r = new QueryStateHolder<GuestBookMessage>(); 
		setCursorFilterSortQuery(s3qlist, r);
		return r;
	}

	public QueryStateHolder<GuestBookMessage>queryMessages(String category, QueryStateHolder<GuestBookMessage>from, int count) {
		if (from==null)
			throw new NullPointerException("queryMessageKeys: from can not be null!");
		if (count<=0 || count>1000)
			throw new NullPointerException("queryMessageKeys: count should be between 1 and 1000!");
		GuestBookMessageMeta meta = GuestBookMessageMeta.get();
		ModelQuery<GuestBookMessage>q = Datastore.query(meta);
		if (!StringUtils.isBlank(category))
			q.filter(meta.categories.equal(category));
		S3QueryResultList<GuestBookMessage>s3qlist = 
			q.encodedCursor(from.getCursor())
			.encodedFilters(from.getFilters())
			.encodedSorts(from.getSorts())
			.limit(count).asQueryResultList();
		QueryStateHolder<GuestBookMessage> r = new QueryStateHolder<GuestBookMessage>(); 
		setCursorFilterSortQuery(s3qlist, r);
		return r;
	}

	private void setCursorFilterSortQuery(S3QueryResultList<GuestBookMessage> s3qlist, QueryStateHolder<GuestBookMessage> r) {
		r.setCursor(s3qlist.getEncodedCursor());
		r.setFilters(s3qlist.getEncodedFilters());
		r.setSorts(s3qlist.getEncodedSorts());
		r.setQueryResult(s3qlist);
	}

	public List<Key> queryMessageKeys(String category, Date from, Date to) {
		GuestBookMessageMeta meta = GuestBookMessageMeta.get();
		ModelQuery<GuestBookMessage>q = Datastore.query(meta);
		if (!StringUtils.isBlank(category))
			q.filter(meta.categories.equal(category));
		return q.filter(meta.createTime.greaterThanOrEqual(from)).limit(LIMIT)
			.sort(meta.createTime.desc).filterInMemory(meta.createTime.lessThan(to))
			.asKeyList();
	}

	public List<GuestBookMessage> fetchMessages(List<Key> keys) {
		return Datastore.get(GuestBookMessageMeta.get(), keys);
	}

	public void replyMessage(Key replyToKey, GuestBookMessage message) {
		Key parentKey = replyToKey.getParent();
		if (parentKey!=null) {
			if (parentKey.getParent()!=null)
				throw new RuntimeException("replyMessage: max depth level is 3");
		}
		Key key = Datastore.allocateId(replyToKey, GuestBookMessage.class);
		message.setKey(key);
		message.setRoot(false);
		if (message.getCreateTime()==null)
			message.setCreateTime(new Date());
		Datastore.put(message);
	}

	public GuestBookMessage getMessage(Key key) {
		return Datastore.getOrNull(GuestBookMessageMeta.get(), key);
	}

	public List<GuestBookMessage> queryMessage(String category, int from, int count) {
		GuestBookMessageMeta meta = GuestBookMessageMeta.get();
		ModelQuery<GuestBookMessage>q = Datastore.query(meta);
		if (!StringUtils.isBlank(category))
			q.filter(meta.categories.equal(category));
		return q.offset(from).limit(count).sort(meta.createTime.desc).asList();
	}
}
